﻿using Elasticsearch.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Nest;
using XYS.Core.Models;
using XYS.Core.Service.APILoggerService;
using XYS.Core.Service.APILoggerService.LoggerWriters;
using XYS.Core.Util;
using XYS.Service.Core.Util.Helper;

namespace XYS.Service.Core
{
    /// <summary>
    /// api接口请求日志 相关配置
    /// </summary>
    public static class APILoggerExtension
    {
        /// <summary>
        /// 添加API请求日志
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="loggerFactory"></param>
        /// <returns></returns>
        public static WebApplicationBuilder AddApiLogger(this WebApplicationBuilder builder, ILoggerFactory loggerFactory)
        {
            var logger = loggerFactory.CreateLogger(typeof(APILoggerExtension));

            //获取配置
            var apiLogSetting = builder.Configuration.GetSection("ApiLoggerSetting").Get<ApiLoggerSetting>();
            if (apiLogSetting != null && apiLogSetting.ChannelType != EnumAPILoggerChannelType.Unknown)
            {
                builder.Services.AddSingleton(s =>
                {
                    var apiLogChannel = s.GetService<IAPILogChannel>();
                    if (apiLogChannel != null)
                    {
                        IAPILoggerService service = new APILoggerService(loggerFactory, apiLogChannel);
                        service.InitAsync().DoNotAwait();
                        return service;
                    }
                    return null;
                });

                logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"正在配置API日志，使用[{apiLogSetting.ChannelType}]通道。");
                switch (apiLogSetting.ChannelType)
                {
                    case EnumAPILoggerChannelType.ElasticSearch:

                        if (apiLogSetting.ElasticSearchSetting != null)
                        {
                            //获取配置的 索引 名称
                            string indexName = string.IsNullOrWhiteSpace(apiLogSetting.ElasticSearchSetting.IndexName) ? "api_request_log" : apiLogSetting.ElasticSearchSetting.IndexName;

                            //获取 配置 ElasticSearchSetting
                            var elasticSettings = builder.Configuration.GetSection("ElasticSettings").Get<List<ElasticSearchSetting>>();
                            if (elasticSettings != null)
                            {
                                var elasticSetting = elasticSettings.FirstOrDefault(e => e.ElasticName == apiLogSetting.ElasticSearchSetting.ElasticName);
                                if (elasticSetting != null)
                                {
                                    var settings = new ConnectionSettings(new SingleNodeConnectionPool(new Uri(elasticSetting.ElasticSearchHost)))
                                        .EnableTcpKeepAlive(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(2))
                                        .MaximumRetries(5)
                                        .DefaultIndex(apiLogSetting.ElasticSearchSetting.IndexName);
                                    //创建客户端对象
                                    IElasticClient client = new ElasticClient(settings);

                                    builder.Services.AddSingleton<IAPILogChannel>(s => new ElasticSearchCannel(client));
                                    logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"已成功加载[ElasticSearch]通道,ElasticSearch连接名：[{elasticSetting.ElasticName}]。indexName:[{indexName}]");
                                }
                                else logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"未找到名字为[{apiLogSetting.ElasticSearchSetting.ElasticName}]的ElasticSearch配置。indexName:[{indexName}]");
                            }
                            else logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"未找到名字为[{apiLogSetting.ElasticSearchSetting.ElasticName}]的ElasticSearch配置。indexName:[{indexName}]");
                        }
                        return builder;
                    case EnumAPILoggerChannelType.File:
                        builder.Services.AddSingleton<IAPILogChannel>(s => new FileChannel());
                        logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"已成功加载[File]通道。");
                        return builder;
                    default:
                        logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"尚未实现[{apiLogSetting.ChannelType}]通道。");
                        return builder;
                }
            }
            logger.Log(Microsoft.Extensions.Logging.LogLevel.Warning, "您尚未配置API日志(ApiLoggerSetting)，请求将不会被记录");
            return builder;
        }


        /// <summary>
        /// 添加http请求日志
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="logger"></param>
        /// <returns></returns>
        public static WebApplicationBuilder AddHttpLogger(this WebApplicationBuilder builder, ILogger logger)
        {
            //获取配置
            var httpLogSetting = builder.Configuration.GetSection("HttpLoggerSetting").Get<HttpLoggerSetting>();
            if (httpLogSetting != null && httpLogSetting.ChannelType != EnumAPILoggerChannelType.Unknown)
            {
                logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"正在配置Http日志，使用[{httpLogSetting.ChannelType}]通道。");
                LogHelperSetting.LoggerChannelType = httpLogSetting.ChannelType;
                switch (httpLogSetting.ChannelType)
                {
                    case EnumAPILoggerChannelType.ElasticSearch:

                        if (httpLogSetting.ElasticSearchSetting != null)
                        {
                            //获取配置的 索引 名称
                            string indexName = string.IsNullOrWhiteSpace(httpLogSetting.ElasticSearchSetting.IndexName) ? "http_request_log" : httpLogSetting.ElasticSearchSetting.IndexName;

                            //获取 配置 ElasticSearchSetting
                            var elasticSettings = builder.Configuration.GetSection("ElasticSettings").Get<List<ElasticSearchSetting>>();
                            if (elasticSettings != null)
                            {
                                var elasticSetting = elasticSettings.FirstOrDefault(e => e.ElasticName == httpLogSetting.ElasticSearchSetting.ElasticName);
                                if (elasticSetting != null)
                                {
                                    var settings = new ConnectionSettings(new SingleNodeConnectionPool(new Uri(elasticSetting.ElasticSearchHost)))
                                        .EnableTcpKeepAlive(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(2))
                                        .MaximumRetries(5)
                                        .DefaultIndex(httpLogSetting.ElasticSearchSetting.IndexName);
                                    LogHelperSetting.ESClient = new ElasticClient(settings);
                                    LogHelperSetting.DefaultIndex = httpLogSetting.ElasticSearchSetting.IndexName;

                                    logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"已成功加载[ElasticSearch]通道。indexName:[{indexName}]");
                                }
                                else logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"未找到名字为[{httpLogSetting.ElasticSearchSetting.ElasticName}]的ElasticSearch配置。indexName:[{indexName}]");
                            }
                            else logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"未找到名字为[{httpLogSetting.ElasticSearchSetting.ElasticName}]的ElasticSearch配置。indexName:[{indexName}]");
                        }
                        return builder;
                    case EnumAPILoggerChannelType.File:
                        logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"已成功加载[File]通道。");
                        return builder;
                    default:
                        logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, $"尚未实现[{httpLogSetting.ChannelType}]通道。");
                        return builder;
                }
            }
            logger.Log(Microsoft.Extensions.Logging.LogLevel.Warning, "您尚未配置Http日志(HttpLoggerSetting)，HttpHelper的请求将不会被记录");
            return builder;
        }




    }
}
